import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

import '../../core/network/api/list_view_model.dart';
import 'keep_book_refresher.dart';
import 'keep_book_toast.dart';
import 'placeholder/empty_placeholder.dart';
import 'placeholder/loading_placeholder.dart';


/// 列表。
abstract class KeepBookListView<T> extends StatefulWidget {
  const KeepBookListView({
    super.key,
    required this.viewModel,
    this.enablePullDown = true,
    this.enablePullUp = true,
    this.onLoaded,
  });

  /// 列表数据
   final ListViewModel<T> viewModel;

  /// 下拉是否可用
  final bool enablePullDown;

  /// 上拉是否可用
  final bool enablePullUp;

  /// 页面加载成功回调。
  final VoidCallback? onLoaded;
}

abstract class KeepBookListViewState<T> extends State<KeepBookListView<T>> {
  late KeepBookRefreshController refreshController;

  bool enablePullDown = true;
  bool enablePullUp = true;

  List<T>? get list => widget.viewModel.list;
  int get itemCount => list?.length ?? 0;

  late final mq = MediaQuery.of(context);
  double get safeBottom => mq.padding.bottom;

  @override
  void initState() {
    super.initState();

    refreshController = KeepBookRefreshController();
    widget.viewModel.addListener(onNotifyReload);

    if (list == null) {
      enablePullDown = false;
      enablePullUp = false;
      onRefresherRefresh();
    }
  }

  @override
  void dispose() {
    refreshController.dispose();
    widget.viewModel.removeListener(onNotifyReload);
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant KeepBookListView<T> oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.viewModel == widget.viewModel) {
      return;
    }

    oldWidget.viewModel.removeListener(onNotifyReload);
    widget.viewModel.addListener(onNotifyReload);

    refreshController.resetNoData();

    // 如果 view model 变更了，且新的 view model 没有数据，则主动请求一次数据
    if (list == null) {
      enablePullDown = false;
      enablePullUp = false;
      onRefresherRefresh();
    } else {
      enablePullDown = true;
      enablePullUp = widget.viewModel.hasNextPage;
    }
  }

  @override
  Widget build(BuildContext context) {
    return stateBody;
  }

  Widget get stateBody {
    if (list == null) {
      return loadingPlaceholder;
    }

    if (widget.viewModel.isFailedOnFirstRequest) {
      return networkPlaceholder;
    }

    return body;
  }

  Widget get body => MagicRefresher(
        controller: refreshController,
        enablePullDown: enablePullDown && widget.enablePullDown,
        enablePullUp: enablePullUp && widget.enablePullUp,
        onRefresh: onRefresherRefresh,
        onLoading: onRefresherLoading,
        child: itemCount > 0 ? listView : emptyPlaceholder,
      );

  /// 无内容占位
  Widget get emptyPlaceholder => const EmptyPlaceholder(
        text: '空空如也~',
        yOffset: -60,
      );

  /// 网络错误占位
  Widget get networkPlaceholder => EmptyPlaceholder.networkError(
        yOffset: -60,
        onTapButton: () {
          widget.viewModel.reset();
          setState(() {});
          onRefresherRefresh();
        },
      );

  /// loading
  Widget get loadingPlaceholder => const LoadingPlaceholder();

  Widget get listView {
    int additions = 0;
    if (hasHeader) {
      additions += 1;
    }
    if (hasFooter) {
      additions += 1;
    }
    return ListView.separated(
      padding: listPadding,
      itemCount: itemCount + additions,
      itemBuilder: (context, index) {
        if (hasHeader) {
          if (index == 0) return headerWidget ?? Container();
          index -= 1;
        }
        if (hasFooter) {
          if (index == itemCount) return footerWidget ?? Container();
        }
        return itemBuilder(context, index, list![index]);
      },
      separatorBuilder: (context, index) {
        if (hasHeader) {
          if (index == 0) return Container();
          index -= 1;
        }
        if (hasFooter) {
          if (index >= itemCount - 1) return Container();
        }
        return separatorBuilder(context, index);
      },
    );
  }

  /// 列表边距。默认为 (left: 10, right: 10, top: 0, bottom: 30)。
  EdgeInsets get listPadding => const EdgeInsets.only(left: 10, right: 10, bottom: 30);

  bool get hasHeader => false;
  Widget? get headerWidget => null;

  bool get hasFooter => false;
  Widget? get footerWidget => null;

  /// 列表 separator
  Widget separatorBuilder(BuildContext context, int index) {
    final height = separatorHeight;
    if (height != null) {
      return SizedBox(height: height);
    }

    return const SizedBox(height: 6);
  }

  /// 列表 separator 高度。默认为 6。
  double? get separatorHeight => 6;

  /// 列表 item
  Widget itemBuilder(BuildContext context, int index, T value) {
    assert(false, '子类继承后实现自定义列表 item');
    return Container();
  }

  /// 刷新列表
  Future<void> onRefresherRefresh() async {
    final result = await widget.viewModel.requestFirstPage();

    enablePullDown = true;

    if (result.isFailed) {
      refreshController.refreshFailed();
      if (mounted) {
        KeepBookToast.showToast(msg: result.msg, context: context);
      }
    } else {
      refreshController.refreshCompleted(resetFooterState: true);

      final itemCount = result.data?.length ?? 0;
      enablePullUp = itemCount >= widget.viewModel.perPage;
    }

    if (mounted) {
      setState(() {});
    }

    widget.onLoaded?.call();
  }

  /// 加载更多
  Future<void> onRefresherLoading() async {
    await Future.delayed(const Duration(milliseconds: 300));
    final result = await widget.viewModel.requestNextPage();

    if (result.isFailed) {
      refreshController.loadFailed();
      if (mounted) {
        KeepBookToast.showToast(msg: result.msg, context: context);
      }
      return;
    }

    if (mounted) {
      setState(() {});
    }

    final itemCount = result.data?.length ?? 0;

    if (itemCount > 0) {
      refreshController.loadComplete();
    } else {
      refreshController.loadNoData();
    }
  }

  void onNotifyReload() => reloadData();

  /// 刷新列表数据。（不触发显示 refresh header）
  void reloadData() {
    if (widget.viewModel.itemCount == 0 && widget.viewModel.isFailedOnFirstRequest) {
      widget.viewModel.reset();
    }

    enablePullDown = false;
    enablePullUp = false;

    if (mounted) {
      setState(() {});
      onRefresherRefresh();
    } else {
      widget.viewModel.reset();
    }
  }
}
